Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Displaying Raw • Download


meshchatx/src/backend/database/stickers.py c0b0ddffd735a0d007c1be9a5e8563ec42fdafc0 (c0b0ddff) Text, 14.05 KB

T8b949e# SPDX-License-Identifier: 0BSD

Tff7b72import T7ee787base64
Tff7b72import T7ee787sqlite3
Tff7b72import T7ee787time

Tff7b72from T7ee787meshchatxT7ee787.T7ee787srcT7ee787.T7ee787backend Tff7b72import Te6edf3sticker_utils

Te6edf3_STICKER_SUMMARY_COLUMNS Tff7b72= Tb4b4b4(
Ta5d6ff"Ta5d6ffid, identity_hash, name, image_type, length(image_blob) AS image_size, Ta5d6ff"
Ta5d6ff"Ta5d6ffcontent_hash, source_message_hash, pack_id, emoji, width, height, Ta5d6ff"
Ta5d6ff"Ta5d6ffduration_ms, fps, is_animated, is_video, is_strict, sort_order, Ta5d6ff"
Ta5d6ff"Ta5d6ffcreated_at, updated_atTa5d6ff"
Tb4b4b4)

Te6edf3_STICKER_FULL_COLUMNS Tff7b72= Tb4b4b4(
Ta5d6ff"Ta5d6ffid, identity_hash, name, image_type, image_blob, content_hash, Ta5d6ff"
Ta5d6ff"Ta5d6ffsource_message_hash, pack_id, emoji, width, height, duration_ms, fps, Ta5d6ff"
Ta5d6ff"Ta5d6ffis_animated, is_video, is_strict, sort_order, created_at, updated_atTa5d6ff"
Tb4b4b4)


Tff7b72class T56d364UserStickersDAOTb4b4b4:
T8b949e"""Data access object for individual stickers stored per identity."""

Tff7b72def Tff7b72__init__Tb4b4b4(Tff7b72selfTb4b4b4, Te6edf3providerTb4b4b4)Tb4b4b4:
Tff7b72selfTff7b72.Td2a8ffprovider Tff7b72= Te6edf3provider

Tff7b72def Td2a8ffcount_for_identityTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657intTb4b4b4:
T8b949e"""Return the total number of stickers stored for identity_hash."""
Te6edf3row Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchoneTb4b4b4(
Ta5d6ff"Ta5d6ffSELECT COUNT(*) AS c FROM user_stickers WHERE identity_hash = ?Ta5d6ff"Tb4b4b4,
Tb4b4b4(Te6edf3identity_hashTb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72return Tffa657intTb4b4b4(Te6edf3rowTb4b4b4[Ta5d6ff"Ta5d6ffcTa5d6ff"Tb4b4b4]Tb4b4b4) Tff7b72if Te6edf3row Tff7b72else T79c0ff0

Tff7b72def Td2a8ffcount_for_packTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3pack_idTb4b4b4: Tffa657intTb4b4b4, Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657intTb4b4b4:
T8b949e"""Return the number of stickers belonging to pack_id."""
Te6edf3row Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchoneTb4b4b4(
Ta5d6ff"Ta5d6ffSELECT COUNT(*) AS c FROM user_stickers WHERE pack_id = ? AND identity_hash = ?Ta5d6ff"Tb4b4b4,
Tb4b4b4(Te6edf3pack_idTb4b4b4, Te6edf3identity_hashTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72return Tffa657intTb4b4b4(Te6edf3rowTb4b4b4[Ta5d6ff"Ta5d6ffcTa5d6ff"Tb4b4b4]Tb4b4b4) Tff7b72if Te6edf3row Tff7b72else T79c0ff0

Tff7b72def Td2a8fflist_for_identityTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4)Tb4b4b4:
T8b949e"""List all sticker summaries for identity_hash, newest first."""
Tff7b72return Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchallTb4b4b4(
Ta5d6fffTa5d6ff"""
Ta5d6ff SELECT Tffd700{Te6edf3_STICKER_SUMMARY_COLUMNSTffd700}
Ta5d6ff FROM user_stickers
Ta5d6ff WHERE identity_hash = ?
Ta5d6ff ORDER BY updated_at DESC, id DESC
Ta5d6ff Ta5d6ff"""Tb4b4b4,
Tb4b4b4(Te6edf3identity_hashTb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72def Td2a8fflist_for_packTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3pack_idTb4b4b4: Tffa657intTb4b4b4, Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4)Tb4b4b4:
T8b949e"""List sticker summaries belonging to a pack, ordered by sort_order."""
Tff7b72return Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchallTb4b4b4(
Ta5d6fffTa5d6ff"""
Ta5d6ff SELECT Tffd700{Te6edf3_STICKER_SUMMARY_COLUMNSTffd700}
Ta5d6ff FROM user_stickers
Ta5d6ff WHERE pack_id = ? AND identity_hash = ?
Ta5d6ff ORDER BY sort_order ASC, id ASC
Ta5d6ff Ta5d6ff"""Tb4b4b4,
Tb4b4b4(Te6edf3pack_idTb4b4b4, Te6edf3identity_hashTb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72def Td2a8fflist_unpackedTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4)Tb4b4b4:
T8b949e"""List sticker summaries that do not belong to any pack."""
Tff7b72return Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchallTb4b4b4(
Ta5d6fffTa5d6ff"""
Ta5d6ff SELECT Tffd700{Te6edf3_STICKER_SUMMARY_COLUMNSTffd700}
Ta5d6ff FROM user_stickers
Ta5d6ff WHERE identity_hash = ? AND pack_id IS NULL
Ta5d6ff ORDER BY updated_at DESC, id DESC
Ta5d6ff Ta5d6ff"""Tb4b4b4,
Tb4b4b4(Te6edf3identity_hashTb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72def Td2a8ffget_rowTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3sticker_idTb4b4b4: Tffa657intTb4b4b4, Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4)Tb4b4b4:
T8b949e"""Fetch the full row (including image_blob) for a sticker."""
Tff7b72return Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchoneTb4b4b4(
Ta5d6fffTa5d6ff"""
Ta5d6ff SELECT Tffd700{Te6edf3_STICKER_FULL_COLUMNSTffd700}
Ta5d6ff FROM user_stickers
Ta5d6ff WHERE id = ? AND identity_hash = ?
Ta5d6ff Ta5d6ff"""Tb4b4b4,
Tb4b4b4(Te6edf3sticker_idTb4b4b4, Te6edf3identity_hashTb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72def Td2a8ffdeleteTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3sticker_idTb4b4b4: Tffa657intTb4b4b4, Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
T8b949e"""Delete a single sticker. Returns True when a row was removed."""
Te6edf3cur Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffexecuteTb4b4b4(
Ta5d6ff"Ta5d6ffDELETE FROM user_stickers WHERE id = ? AND identity_hash = ?Ta5d6ff"Tb4b4b4,
Tb4b4b4(Te6edf3sticker_idTb4b4b4, Te6edf3identity_hashTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3curTff7b72.Td2a8ffrowcount Tff7b72> T79c0ff0

Tff7b72def Td2a8ffdelete_all_for_identityTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657intTb4b4b4:
T8b949e"""Delete every sticker (and dissociate packs) for an identity."""
Te6edf3cur Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffexecuteTb4b4b4(
Ta5d6ff"Ta5d6ffDELETE FROM user_stickers WHERE identity_hash = ?Ta5d6ff"Tb4b4b4,
Tb4b4b4(Te6edf3identity_hashTb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3curTff7b72.Td2a8ffrowcount

Tff7b72def Td2a8ffdelete_all_for_packTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3pack_idTb4b4b4: Tffa657intTb4b4b4, Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657intTb4b4b4:
T8b949e"""Delete every sticker that belongs to pack_id."""
Te6edf3cur Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffexecuteTb4b4b4(
Ta5d6ff"Ta5d6ffDELETE FROM user_stickers WHERE pack_id = ? AND identity_hash = ?Ta5d6ff"Tb4b4b4,
Tb4b4b4(Te6edf3pack_idTb4b4b4, Te6edf3identity_hashTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3curTff7b72.Td2a8ffrowcount

Tff7b72def Td2a8ffupdate_nameTb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3sticker_idTb4b4b4: Tffa657intTb4b4b4,
Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4,
Te6edf3nameTb4b4b4: Tffa657str Tff7b72| Tff7b72NoneTb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
T8b949e"""Update the user-friendly name of a sticker."""
Te6edf3now Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Te6edf3cur Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffexecuteTb4b4b4(
T8b949e"""
UPDATE user_stickers
SET name = ?, updated_at = ?
WHERE id = ? AND identity_hash = ?
"""Tb4b4b4,
Tb4b4b4(Te6edf3nameTb4b4b4, Te6edf3nowTb4b4b4, Te6edf3sticker_idTb4b4b4, Te6edf3identity_hashTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3curTff7b72.Td2a8ffrowcount Tff7b72> T79c0ff0

Tff7b72def Td2a8ffupdate_emojiTb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3sticker_idTb4b4b4: Tffa657intTb4b4b4,
Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4,
Te6edf3emojiTb4b4b4: Tffa657str Tff7b72| Tff7b72NoneTb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
T8b949e"""Update the optional emoji tag for a sticker."""
Te6edf3now Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Te6edf3cur Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffexecuteTb4b4b4(
T8b949e"""
UPDATE user_stickers
SET emoji = ?, updated_at = ?
WHERE id = ? AND identity_hash = ?
"""Tb4b4b4,
Tb4b4b4(Te6edf3emojiTb4b4b4, Te6edf3nowTb4b4b4, Te6edf3sticker_idTb4b4b4, Te6edf3identity_hashTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3curTff7b72.Td2a8ffrowcount Tff7b72> T79c0ff0

Tff7b72def Td2a8ffassign_to_packTb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3sticker_idTb4b4b4: Tffa657intTb4b4b4,
Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4,
Te6edf3pack_idTb4b4b4: Tffa657int Tff7b72| Tff7b72NoneTb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tffa657boolTb4b4b4:
T8b949e"""Move a sticker into a pack or back into the unpacked area."""
Te6edf3now Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Te6edf3cur Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffexecuteTb4b4b4(
T8b949e"""
UPDATE user_stickers
SET pack_id = ?, updated_at = ?
WHERE id = ? AND identity_hash = ?
"""Tb4b4b4,
Tb4b4b4(Te6edf3pack_idTb4b4b4, Te6edf3nowTb4b4b4, Te6edf3sticker_idTb4b4b4, Te6edf3identity_hashTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3curTff7b72.Td2a8ffrowcount Tff7b72> T79c0ff0

Tff7b72def Td2a8ffinsertTb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4,
Te6edf3nameTb4b4b4: Tffa657str Tff7b72| Tff7b72NoneTb4b4b4,
Te6edf3image_typeTb4b4b4: Tffa657strTb4b4b4,
Te6edf3image_bytesTb4b4b4: Tffa657bytesTb4b4b4,
Te6edf3source_message_hashTb4b4b4: Tffa657str Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Tff7b72*Tb4b4b4,
Te6edf3pack_idTb4b4b4: Tffa657int Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Te6edf3emojiTb4b4b4: Tffa657str Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Te6edf3strictTb4b4b4: Tffa657bool Tff7b72= Tff7b72FalseTb4b4b4,
Te6edf3sort_orderTb4b4b4: Tffa657int Tff7b72= T79c0ff0Tb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tffa657dict Tff7b72| Tff7b72NoneTb4b4b4:
T8b949e"""Insert a sticker. Returns None if a duplicate (by content hash).

Validates the payload against the legacy or strict Telegram rules
depending on strict. Extracts and stores width/height/fps/duration
metadata so the picker can render the sticker correctly without
re-parsing.
"""
Tff7b72if Tb4b4b4(
Tff7b72selfTff7b72.Td2a8ffcount_for_identityTb4b4b4(Te6edf3identity_hashTb4b4b4)
Tff7b72>Tff7b72= Te6edf3sticker_utilsTff7b72.Td2a8ffMAX_STICKERS_PER_IDENTITY
Tb4b4b4)Tb4b4b4:
Te6edf3msg Tff7b72= Ta5d6ff"Ta5d6ffsticker_limit_reachedTa5d6ff"
Tff7b72raise Tf85149ValueErrorTb4b4b4(Te6edf3msgTb4b4b4)

Te6edf3ntTb4b4b4, Te6edf3ch Tff7b72= Te6edf3sticker_utilsTff7b72.Td2a8ffvalidate_sticker_payloadTb4b4b4(
Te6edf3image_bytesTb4b4b4,
Te6edf3image_typeTb4b4b4,
Te6edf3strictTff7b72=Te6edf3strictTb4b4b4,
Tb4b4b4)
Te6edf3meta Tff7b72= Te6edf3sticker_utilsTff7b72.Td2a8ffextract_metadataTb4b4b4(Te6edf3ntTb4b4b4, Tffa657bytesTb4b4b4(Te6edf3image_bytesTb4b4b4)Tb4b4b4)
Te6edf3now Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72tryTb4b4b4:
Te6edf3cur Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffexecuteTb4b4b4(
T8b949e"""
INSERT INTO user_stickers (
identity_hash, name, image_type, image_blob, content_hash,
source_message_hash, pack_id, emoji, width, height,
duration_ms, fps, is_animated, is_video, is_strict,
sort_order, created_at, updated_at
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
"""Tb4b4b4,
Tb4b4b4(
Te6edf3identity_hashTb4b4b4,
Te6edf3nameTb4b4b4,
Te6edf3ntTb4b4b4,
Te6edf3image_bytesTb4b4b4,
Te6edf3chTb4b4b4,
Te6edf3source_message_hashTb4b4b4,
Te6edf3pack_idTb4b4b4,
Te6edf3sticker_utilsTff7b72.Td2a8ffsanitize_sticker_emojiTb4b4b4(Te6edf3emojiTb4b4b4)Tb4b4b4,
Te6edf3metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffwidthTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffheightTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffduration_msTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffpsTa5d6ff"Tb4b4b4)Tb4b4b4,
T79c0ff1 Tff7b72if Te6edf3metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffis_animatedTa5d6ff"Tb4b4b4) Tff7b72else T79c0ff0Tb4b4b4,
T79c0ff1 Tff7b72if Te6edf3metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffis_videoTa5d6ff"Tb4b4b4) Tff7b72else T79c0ff0Tb4b4b4,
T79c0ff1 Tff7b72if Te6edf3strict Tff7b72else T79c0ff0Tb4b4b4,
Tffa657intTb4b4b4(Te6edf3sort_order Tff7b72or T79c0ff0Tb4b4b4)Tb4b4b4,
Te6edf3nowTb4b4b4,
Te6edf3nowTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72except Te6edf3sqlite3Tff7b72.Td2a8ffIntegrityErrorTb4b4b4:
Tff7b72return Tff7b72None

Te6edf3new_id Tff7b72= Te6edf3curTff7b72.Td2a8fflastrowid
Te6edf3row Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchoneTb4b4b4(
Ta5d6fffTa5d6ff"""
Ta5d6ff SELECT Tffd700{Te6edf3_STICKER_SUMMARY_COLUMNSTffd700}
Ta5d6ff FROM user_stickers
Ta5d6ff WHERE id = ?
Ta5d6ff Ta5d6ff"""Tb4b4b4,
Tb4b4b4(Te6edf3new_idTb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72return Tffa657dictTb4b4b4(Te6edf3rowTb4b4b4) Tff7b72if Te6edf3row Tff7b72else Tff7b72None

Tff7b72def Td2a8ffexport_payloads_for_identityTb4b4b4(Tff7b72selfTb4b4b4, Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4) Tff7b72-Tff7b72> Tffa657listTb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4:
T8b949e"""Return base64-encoded payloads suitable for JSON export."""
Te6edf3rows Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchallTb4b4b4(
T8b949e"""
SELECT name, image_type, image_blob, source_message_hash, emoji
FROM user_stickers
WHERE identity_hash = ?
ORDER BY id ASC
"""Tb4b4b4,
Tb4b4b4(Te6edf3identity_hashTb4b4b4,Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3out Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3r Tff7b72in Te6edf3rowsTb4b4b4:
Te6edf3blob Tff7b72= Te6edf3rTb4b4b4[Ta5d6ff"Ta5d6ffimage_blobTa5d6ff"Tb4b4b4]
Te6edf3b64 Tff7b72= Te6edf3base64Tff7b72.Td2a8ffb64encodeTb4b4b4(Te6edf3blobTb4b4b4)Tff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffasciiTa5d6ff"Tb4b4b4)
Te6edf3outTff7b72.Td2a8ffappendTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Te6edf3rTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffimage_typeTa5d6ff"Tb4b4b4: Te6edf3rTb4b4b4[Ta5d6ff"Ta5d6ffimage_typeTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffimage_bytesTa5d6ff"Tb4b4b4: Te6edf3b64Tb4b4b4,
Ta5d6ff"Ta5d6ffsource_message_hashTa5d6ff"Tb4b4b4: Te6edf3rTb4b4b4[Ta5d6ff"Ta5d6ffsource_message_hashTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffemojiTa5d6ff"Tb4b4b4: Te6edf3rTb4b4b4[Ta5d6ff"Ta5d6ffemojiTa5d6ff"Tb4b4b4]Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3out

Tff7b72def Td2a8ffexport_payloads_for_packTb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3pack_idTb4b4b4: Tffa657intTb4b4b4,
Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tffa657listTb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4:
T8b949e"""Return base64-encoded payloads for a single pack, in display order."""
Te6edf3rows Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchallTb4b4b4(
T8b949e"""
SELECT name, image_type, image_blob, emoji
FROM user_stickers
WHERE pack_id = ? AND identity_hash = ?
ORDER BY sort_order ASC, id ASC
"""Tb4b4b4,
Tb4b4b4(Te6edf3pack_idTb4b4b4, Te6edf3identity_hashTb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3out Tff7b72= Tb4b4b4[Tb4b4b4]
Tff7b72for Te6edf3r Tff7b72in Te6edf3rowsTb4b4b4:
Te6edf3b64 Tff7b72= Te6edf3base64Tff7b72.Td2a8ffb64encodeTb4b4b4(Te6edf3rTb4b4b4[Ta5d6ff"Ta5d6ffimage_blobTa5d6ff"Tb4b4b4]Tb4b4b4)Tff7b72.Td2a8ffdecodeTb4b4b4(Ta5d6ff"Ta5d6ffasciiTa5d6ff"Tb4b4b4)
Te6edf3outTff7b72.Td2a8ffappendTb4b4b4(
Tb4b4b4{
Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4: Te6edf3rTb4b4b4[Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffemojiTa5d6ff"Tb4b4b4: Te6edf3rTb4b4b4[Ta5d6ff"Ta5d6ffemojiTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffimage_typeTa5d6ff"Tb4b4b4: Te6edf3rTb4b4b4[Ta5d6ff"Ta5d6ffimage_typeTa5d6ff"Tb4b4b4]Tb4b4b4,
Ta5d6ff"Ta5d6ffimage_bytesTa5d6ff"Tb4b4b4: Te6edf3b64Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72return Te6edf3out

Tff7b72def Td2a8ffimport_payloadsTb4b4b4(
Tff7b72selfTb4b4b4,
Te6edf3identity_hashTb4b4b4: Tffa657strTb4b4b4,
Te6edf3itemsTb4b4b4: Tffa657listTb4b4b4[Tffa657dictTb4b4b4]Tb4b4b4,
Tff7b72*Tb4b4b4,
Te6edf3replace_duplicatesTb4b4b4: Tffa657boolTb4b4b4,
Te6edf3pack_idTb4b4b4: Tffa657int Tff7b72| Tff7b72None Tff7b72= Tff7b72NoneTb4b4b4,
Te6edf3strictTb4b4b4: Tffa657bool Tff7b72= Tff7b72FalseTb4b4b4,
Tb4b4b4) Tff7b72-Tff7b72> Tffa657dictTb4b4b4:
T8b949e"""Import a list of validated sticker payloads into the library."""
Te6edf3imported Tff7b72= T79c0ff0
Te6edf3skipped_duplicates Tff7b72= T79c0ff0
Te6edf3skipped_invalid Tff7b72= T79c0ff0
Te6edf3errorsTb4b4b4: Tffa657listTb4b4b4[Tffa657strTb4b4b4] Tff7b72= Tb4b4b4[Tb4b4b4]

Tff7b72for Te6edf3iTb4b4b4, Te6edf3item Tff7b72in Tffa657enumerateTb4b4b4(Te6edf3itemsTb4b4b4)Tb4b4b4:
Te6edf3name Tff7b72= Te6edf3sticker_utilsTff7b72.Td2a8ffsanitize_sticker_nameTb4b4b4(Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffnameTa5d6ff"Tb4b4b4)Tb4b4b4)
Te6edf3it Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffimage_typeTa5d6ff"Tb4b4b4)
Te6edf3b64 Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffimage_bytes_b64Ta5d6ff"Tb4b4b4)
Te6edf3src Tff7b72= Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffsource_message_hashTa5d6ff"Tb4b4b4)
Te6edf3emoji Tff7b72= Te6edf3sticker_utilsTff7b72.Td2a8ffsanitize_sticker_emojiTb4b4b4(Te6edf3itemTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffemojiTa5d6ff"Tb4b4b4)Tb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72if Tff7b72not Tffa657isinstanceTb4b4b4(Te6edf3b64Tb4b4b4, Tb4b4b4(Tffa657strTb4b4b4, Tffa657bytesTb4b4b4)Tb4b4b4) Tff7b72or Tff7b72not Te6edf3b64Tb4b4b4:
Te6edf3skipped_invalid Tff7b72+Tff7b72= T79c0ff1
Te6edf3errorsTff7b72.Td2a8ffappendTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffdecode_failed_at_Tffd700{Te6edf3iTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72continue
Te6edf3raw Tff7b72= Te6edf3base64Tff7b72.Td2a8ffb64decodeTb4b4b4(Te6edf3b64Tb4b4b4, Te6edf3validateTff7b72=Tff7b72FalseTb4b4b4)
Tff7b72except Tb4b4b4(Tf85149ValueErrorTb4b4b4, Tf85149TypeErrorTb4b4b4)Tb4b4b4:
Te6edf3skipped_invalid Tff7b72+Tff7b72= T79c0ff1
Te6edf3errorsTff7b72.Td2a8ffappendTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffdecode_failed_at_Tffd700{Te6edf3iTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72continue
Tff7b72tryTb4b4b4:
Te6edf3ntTb4b4b4, Te6edf3ch Tff7b72= Te6edf3sticker_utilsTff7b72.Td2a8ffvalidate_sticker_payloadTb4b4b4(Te6edf3rawTb4b4b4, Te6edf3itTb4b4b4, Te6edf3strictTff7b72=Te6edf3strictTb4b4b4)
Tff7b72except Tf85149ValueError Tff7b72as Te6edf3excTb4b4b4:
Te6edf3skipped_invalid Tff7b72+Tff7b72= T79c0ff1
Te6edf3errorsTff7b72.Td2a8ffappendTb4b4b4(Ta5d6fffTa5d6ff"Ta5d6ffinvalid_payload_at_Tffd700{Te6edf3iTffd700}Ta5d6ff:Tffd700{Te6edf3excTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72continue

Te6edf3existing Tff7b72= Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8fffetchoneTb4b4b4(
Ta5d6ff"Ta5d6ffSELECT id FROM user_stickers WHERE identity_hash = ? AND content_hash = ?Ta5d6ff"Tb4b4b4,
Tb4b4b4(Te6edf3identity_hashTb4b4b4, Te6edf3chTb4b4b4)Tb4b4b4,
Tb4b4b4)
Tff7b72if Te6edf3existingTb4b4b4:
Tff7b72if Tff7b72not Te6edf3replace_duplicatesTb4b4b4:
Te6edf3skipped_duplicates Tff7b72+Tff7b72= T79c0ff1
Tff7b72continue
Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffexecuteTb4b4b4(
Ta5d6ff"Ta5d6ffDELETE FROM user_stickers WHERE identity_hash = ? AND content_hash = ?Ta5d6ff"Tb4b4b4,
Tb4b4b4(Te6edf3identity_hashTb4b4b4, Te6edf3chTb4b4b4)Tb4b4b4,
Tb4b4b4)

Tff7b72if Tb4b4b4(
Tff7b72selfTff7b72.Td2a8ffcount_for_identityTb4b4b4(Te6edf3identity_hashTb4b4b4)
Tff7b72>Tff7b72= Te6edf3sticker_utilsTff7b72.Td2a8ffMAX_STICKERS_PER_IDENTITY
Tb4b4b4)Tb4b4b4:
Te6edf3errorsTff7b72.Td2a8ffappendTb4b4b4(Ta5d6ff"Ta5d6ffsticker_limit_reachedTa5d6ff"Tb4b4b4)
Tff7b72break

Te6edf3meta Tff7b72= Te6edf3sticker_utilsTff7b72.Td2a8ffextract_metadataTb4b4b4(Te6edf3ntTb4b4b4, Te6edf3rawTb4b4b4)
Te6edf3now Tff7b72= Te6edf3timeTff7b72.Td2a8fftimeTb4b4b4(Tb4b4b4)
Tff7b72tryTb4b4b4:
Tff7b72selfTff7b72.Td2a8ffproviderTff7b72.Td2a8ffexecuteTb4b4b4(
T8b949e"""
INSERT INTO user_stickers (
identity_hash, name, image_type, image_blob, content_hash,
source_message_hash, pack_id, emoji, width, height,
duration_ms, fps, is_animated, is_video, is_strict,
sort_order, created_at, updated_at
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
"""Tb4b4b4,
Tb4b4b4(
Te6edf3identity_hashTb4b4b4,
Te6edf3nameTb4b4b4,
Te6edf3ntTb4b4b4,
Te6edf3rawTb4b4b4,
Te6edf3chTb4b4b4,
Te6edf3src Tff7b72if Tffa657isinstanceTb4b4b4(Te6edf3srcTb4b4b4, Tffa657strTb4b4b4) Tff7b72else Tff7b72NoneTb4b4b4,
Te6edf3pack_idTb4b4b4,
Te6edf3emojiTb4b4b4,
Te6edf3metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffwidthTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffheightTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffduration_msTa5d6ff"Tb4b4b4)Tb4b4b4,
Te6edf3metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6fffpsTa5d6ff"Tb4b4b4)Tb4b4b4,
T79c0ff1 Tff7b72if Te6edf3metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffis_animatedTa5d6ff"Tb4b4b4) Tff7b72else T79c0ff0Tb4b4b4,
T79c0ff1 Tff7b72if Te6edf3metaTff7b72.Td2a8ffgetTb4b4b4(Ta5d6ff"Ta5d6ffis_videoTa5d6ff"Tb4b4b4) Tff7b72else T79c0ff0Tb4b4b4,
T79c0ff1 Tff7b72if Te6edf3strict Tff7b72else T79c0ff0Tb4b4b4,
Te6edf3iTb4b4b4,
Te6edf3nowTb4b4b4,
Te6edf3nowTb4b4b4,
Tb4b4b4)Tb4b4b4,
Tb4b4b4)
Te6edf3imported Tff7b72+Tff7b72= T79c0ff1
Tff7b72except Te6edf3sqlite3Tff7b72.Td2a8ffIntegrityErrorTb4b4b4:
Te6edf3skipped_duplicates Tff7b72+Tff7b72= T79c0ff1

Tff7b72return Tb4b4b4{
Ta5d6ff"Ta5d6ffimportedTa5d6ff"Tb4b4b4: Te6edf3importedTb4b4b4,
Ta5d6ff"Ta5d6ffskipped_duplicatesTa5d6ff"Tb4b4b4: Te6edf3skipped_duplicatesTb4b4b4,
Ta5d6ff"Ta5d6ffskipped_invalidTa5d6ff"Tb4b4b4: Te6edf3skipped_invalidTb4b4b4,
Ta5d6ff"Ta5d6fferrorsTa5d6ff"Tb4b4b4: Te6edf3errorsTb4b4b4,
Tb4b4b4}


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────